package cate.game.role.pay.limittimeggift;

import cate.common.table.d.GDOperation;
import cate.common.table.d.GDTask;
import cate.common.table.limittimegift.LimitTimeGiftRow;
import cate.common.util.GameResult;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.pay.limittimeggift.msg.LimitTimeGiftAdResp;
import cate.game.role.pay.limittimeggift.msg.LimitTimeGiftDataResp;
import cate.game.role.task.conditiontask.ConditionFuncPO;
import cate.game.role.task.conditiontask.ConditionPO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class LimitTimeGift extends ConditionFuncPO {
    public LimitTimeGift() {
    }

    @NoteField(value = "所有触发的礼包", detail = "Map<礼包id，礼包内容>")
    public Map<Integer, CheapItemPO> itemMap;

    @JsonIgnore
    @NoteField(value = "所有礼包CD时间开放记录", detail = "Map<礼包id，时间>")
    public Map<Integer, Long> timeCDMap;

    @JsonIgnore
    @NoteField(value = "下次需要检测的时间")
    public long checkTime;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (itemMap == null) {
            itemMap = new HashMap<>();
        }
        if (!itemMap.isEmpty()) {
            itemMap.entrySet().forEach(item -> item.getValue().initialize(role.getGame()));
            itemMap.entrySet().removeIf(item -> item.getValue().getRow() == null);
        }
        if (timeCDMap == null) {
            timeCDMap = new HashMap<>();
        }
        checkCondition();
        resetCheckTime();
    }

    @Override
    public void onDaySpan() {
        super.onDaySpan();
        checkRecycle(GDTask.Condition.DAY);
    }

    /**
     * 消耗道具购买礼包
     *
     * @param tid 礼包id
     */
    public void buyGift(int tid) {
        EcResult r = checkBuyItem(tid);
        if (!r.ok()) {
            return;
        }
        LimitTimeGiftRow row = getRow(tid);
        if (StringUtils.isBlank(row.propPrice)) {
            role.getGame().notice.message(role, "该礼包不支持使用道具购买");
            return;
        }
        MixRes consumeProp = new MixRes(row.propPrice);
        EcResult<MixResItem> consume = consumeProp.consume(role, null);
        if (consume.ok()) {
            afterPay(tid);
        } else {
            role.getGame().notice.tipResItem(role, consume.data);
        }
    }

    /**
     * 钜惠礼包检测
     */
    public GameResult<Void> checkBuyItem(int tid) {
        GameResult<Void> r = new GameResult<>();
        LimitTimeGiftRow row = getRow(tid);
        if (row == null) {
            return r.fail("配置错误");
        }
        CheapItemPO item = itemMap.get(tid);
        if (item == null) {
            return r.fail("已过期");
        }
        if (item.purchaseNum + 1 > row.limitNum) {
            return r.fail("已售罄");
        }
        return r.success();
    }

    /**
     * 购买成功后
     */
    public void afterPay(int tid) {
        LimitTimeGiftRow row = getRow(tid);
        if (row == null) {
            return;
        }

        role.log.setOperation(GDOperation.LIMIT_GIFT_PACKAGE_BUY);

        MixRes reward = new MixRes(row.rewardStr);
        reward.add(role, true, GDOperation.LIMIT_GIFT_PACKAGE_BUY);
        role.getGame().notice.dialogReward(role, reward);

        role.log.clearOperation();
        CheapItemPO item = itemMap.get(tid);
        if (item != null) {
            item.purchaseNum++;
        }
        noticeUpdate();
    }


    public void resetCheckTime() {
        checkTime = 0L;
        for (CheapItemPO item : itemMap.values()) {
            if (checkTime == 0 || checkTime > item.getExpiredTime()) {
                checkTime = item.getExpiredTime();
            }
        }
    }

    public void tick() {
        if (checkTime == 0 || checkTime > role.getGame().time.now()) {
            return;
        }
        boolean change = false;
        Iterator<Map.Entry<Integer, CheapItemPO>> it = itemMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, CheapItemPO> next = it.next();
            if (next.getValue().expired()) {
                // 礼包推送条件重置
                ConditionPO condition = (ConditionPO) conditionMap.get(next.getKey());
                if (condition != null) {
                    condition.reset(condition.getRow().taskDuration);
                }
                if (getRow(next.getKey()) == null || getRow(next.getKey()).preTid == GDTask.Condition.UN_GROUP) {
                    change = true;
                    it.remove();
                }
                //玩家等级不足该表中礼包最低等级的 删掉所有存在记录 策划改等级礼包用
                if (getRow(next.getKey()).levelMin > role.getBase().level) {
                    change = true;
                    if (timeCDMap.containsKey(next.getKey())) {
                        timeCDMap.remove(next.getKey());
                    }
                    it.remove();
                }
                //前置礼包移除永久记录用于日，周，月循环
                if (next.getValue().recycle) {
                    change = true;
                    it.remove();
                }
            }
        }
        if (change) {
            noticeUpdate();
        }
        resetCheckTime();
    }

    @Override
    protected void selfClear() {
        itemMap.clear();
        checkTime = 0;
    }


    public void noticeUpdate() {
        role.sendNow(new LimitTimeGiftDataResp(role));
    }

    @Override
    protected LimitTimeGiftRow getRow(int tid) {
        return role.getGame().table.limitGift.gift.get(tid);
    }

    @Override
    public List<Integer> checkSelfCondition() {
        // 获取当前满足的推送条件
        List<Integer> tids =
                role.getGame().table.limitGift.gift.getGiftTid(role.getBase().level, role.getBase().vip, role.getGame().status.getOpenDay());
        return tids;
    }

    @Override
    protected void doDone(int tid) {
        pushGift(tid);
    }

    //gm强制推送礼包
    public void gmPushGift(int tid) {
        pushGift(tid);
    }

    /**
     * 推送礼包
     */
    private void pushGift(int tid) {
        // 检测是否有同个礼包

        int preTid = calcPreTid(tid);
        if (preTid != tid) {
            ConditionPO condition = (ConditionPO) conditionMap.get(tid);
            condition.resetDone();
            tid = preTid;
        }
        CheapItemPO item = itemMap.get(tid);

        if (item != null && !item.expired()) {
            return;
        }

        if (!checkCD(tid)) {
            //cd时间内重置条件
            //cd时间过了直接继续执行弹出
            ConditionPO condition = (ConditionPO) conditionMap.get(tid);
            condition.reset();
            return;
        }

        item = new CheapItemPO(role.getGame());
        item.tid = tid;
        item.activeTime = role.getGame().time.now();
        itemMap.put(item.tid, item);
        resetCheckTime();
        role.sendNow(new LimitTimeGiftDataResp(role));
        role.sendNow(new LimitTimeGiftAdResp(tid));
        pushCD(tid, item.activeTime);
    }

    private int calcPreTid(int tid) {
        LimitTimeGiftRow row = getRow(tid);
        LimitTimeGiftRow preRow = getRow(row.preTid);
        while (row.preTid != GDTask.Condition.GROUP_TOP && row.preTid != GDTask.Condition.UN_GROUP) {
            if (preRow == null) {
                logger.info("限时礼包检查配置:" + tid);
                return row.tid;
            }
            if (itemMap.containsKey(row.preTid) && itemMap.get(row.preTid).purchaseNum >= preRow.limitNum) {
                return row.tid;
            }
            row = preRow;
            preRow = getRow(row.preTid);
        }
        return row.tid;
    }

    private void pushCD(int tid, long activeTime) {
        long time = activeTime + getRow(tid).cd * 3600L * 1000L;
        timeCDMap.put(tid, time);
    }

    /**
     * 检查cd过了吗，过了：true;没过：false
     *
     * @param tid
     * @return
     */
    private boolean checkCD(int tid) {
        if (!timeCDMap.containsKey(tid)) {
            return true;
        }
        Long time = timeCDMap.get(tid);
        if (time <= role.getGame().time.now()) {
            return true;
        }
        return false;
    }


    @Override
    public void onWeekSpan() {
        super.onWeekSpan();
        checkRecycle(GDTask.Condition.WEEK);
    }

    @Override
    public void onMonthSpan() {
        super.onMonthSpan();
        checkRecycle(GDTask.Condition.MONTH);
    }

    public void checkRecycle(int type) {
        Iterator<Map.Entry<Integer, CheapItemPO>> it = itemMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, CheapItemPO> next = it.next();
            LimitTimeGiftRow row = getRow(next.getKey());
            if (row == null) {
                continue;
            }
            if (row.preTid != GDTask.Condition.UN_GROUP && type == row.cycleType) {
                if (next.getValue().expired() || next.getValue().purchaseNum >= row.limitNum) {
                    it.remove();
                } else {
                    next.getValue().recycle = true;
                }
            }
        }
    }
}
